using Rogan.Utility.Common;
using Rogan.Utility.Extensions;
using Rogan.Data.MsAccess;
using Rogan.Data.Oracle;
using Rogan.Data.Resources;
using Rogan.Data.SqlServer;
using Rogan.Data.SqlServer9;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.Common;
using System.IO;
namespace Rogan.Data
{
	public class DbContext
	{
		private Database db;
		private CommandBulider cmdBulider;
		public static DbContext Default = new DbContext(Database.Default);
		private DbTrans DbTrans
		{
			get;
			set;
		}
		private CacheConfiguration CacheConfig
		{
			get
			{
				return db.DbProvider.CacheConfig;
			}
		}
		public Database Db
		{
			get
			{
				return db;
			}
		}
		public void TurnOnCache()
		{
			if (CacheConfig != null)
			{
				CacheConfig.Enable = true;
			}
		}
		public void TurnOffCache()
		{
			if (CacheConfig != null)
			{
				CacheConfig.Enable = false;
			}
		}
		public static void SetDefault(DatabaseType dt, string connStr)
		{
			DbProvider dbProvider = CreateDbProvider(dt, connStr);
			Default = new DbContext(new Database(dbProvider));
		}
		private static DbProvider CreateDbProvider(DatabaseType dt, string connStr)
		{
			DbProvider result = null;
			if (dt == DatabaseType.SqlServer9)
			{
				result = ProviderFactory.CreateDbProvider(null, typeof(SqlServer9Provider).FullName, connStr);
			}
			else
			{
				if (dt == DatabaseType.SqlServer)
				{
					result = ProviderFactory.CreateDbProvider(null, typeof(SqlServerProvider).FullName, connStr);
				}
				else
				{
					if (dt == DatabaseType.Oracle)
					{
						result = ProviderFactory.CreateDbProvider(null, typeof(OracleProvider).FullName, connStr);
					}
					else
					{
						if (dt == DatabaseType.MySql)
						{
							result = ProviderFactory.CreateDbProvider("Rogan.Data.MySql", "Rogan.Data.MySql.MySqlProvider", connStr);
						}
						else
						{
							if (dt == DatabaseType.Sqlite3)
							{
								result = ProviderFactory.CreateDbProvider("Rogan.Data.Sqlite", "Rogan.Data.Sqlite.SqliteProvider", connStr);
							}
							else
							{
								if (dt == DatabaseType.MsAccess)
								{
									result = ProviderFactory.CreateDbProvider(null, typeof(MsAccessProvider).FullName, connStr);
								}
							}
						}
					}
				}
			}
			return result;
		}
		public static void SetDefault(string assemblyName, string className, string connStr)
		{
			DbProvider dbProvider = ProviderFactory.CreateDbProvider(assemblyName, className, connStr);
			if (dbProvider == null)
			{
				throw new NotSupportedException(string.Format("Cannot construct DbProvider by specified parameters: {0}, {1}, {2}", assemblyName, className, connStr));
			}
			Default = new DbContext(new Database(dbProvider));
		}
		public static void SetDefault(string connStrName)
		{
			DbProvider dbProvider = ProviderFactory.CreateDbProvider(connStrName);
			dbProvider.ConnectionStringsName = connStrName;
			if (dbProvider == null)
			{
				throw new NotSupportedException(string.Format("Cannot construct DbProvider by specified ConnectionStringName: {0}", connStrName));
			}
			Default = new DbContext(new Database(dbProvider));
		}
		private void initDbSesion()
		{
			cmdBulider = new CommandBulider(db);
			object section = ConfigurationManager.GetSection("LigerCacheConfig");
			if (section != null)
			{
				db.DbProvider.CacheConfig = (section as DbCacheConfiguration);
				initCache();
			}
		}
		private void initCache()
		{
			Dictionary<string, CacheInfo> dictionary = new Dictionary<string, CacheInfo>();
			string[] allKeys = db.DbProvider.CacheConfig.Entities.AllKeys;
			for (int i = 0; i < allKeys.Length; i++)
			{
				string text = allKeys[i];
				if (text.IndexOf('.') > 0)
				{
					string[] array = text.Split(new[]
					{
						'.'
					});
					string key = array[1].Trim();
					if (array[0].Trim() == db.DbProvider.ConnectionStringsName)
					{
						int value = 0;
						CacheInfo cacheInfo = new CacheInfo();
						if (int.TryParse(db.DbProvider.CacheConfig.Entities[text].Value, out value))
						{
							cacheInfo.TimeOut = new int?(value);
						}
						else
						{
							string text2 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, db.DbProvider.CacheConfig.Entities[text].Value);
							if (File.Exists(text2))
							{
								cacheInfo.FilePath = text2;
							}
						}
						if (!cacheInfo.IsNullOrEmpty())
						{
							if (dictionary.ContainsKey(key))
							{
								dictionary.Remove(key);
							}
							dictionary.Add(key, cacheInfo);
						}
					}
				}
			}
			db.DbProvider.EntitiesCache = dictionary;
		}
		public DbContext()
		{
			db = Database.Default;
			initDbSesion();
		}
		public DbContext(string connStrName)
		{
			db = new Database(ProviderFactory.CreateDbProvider(connStrName));
			db.DbProvider.ConnectionStringsName = connStrName;
			initDbSesion();
		}
		public DbContext(Database db)
		{
			this.db = db;
			initDbSesion();
		}
		public DbContext(DatabaseType dt, string connStr)
		{
			DbProvider dbProvider = CreateDbProvider(dt, connStr);
			Guard.Check(dbProvider != null, "Cannot construct DbProvider by specified parameters: {0}".FormatWith(new object[]
			{
				connStr
			}));
			db = new Database(dbProvider);
			initDbSesion();
		}
		public DbContext(string assemblyName, string className, string connStr)
		{
			DbProvider dbProvider = ProviderFactory.CreateDbProvider(assemblyName, className, connStr);
			Guard.Check(dbProvider != null, "Cannot construct DbProvider by specified parameters: {0}, {1}, {2}".FormatWith(new object[]
			{
				assemblyName,
				className,
				connStr
			}));
			db = new Database(dbProvider);
			cmdBulider = new CommandBulider(db);
			initDbSesion();
		}
		public EntityQueryable<T> From<T>() where T : Entity
		{
			return new EntityQueryable<T>(db);
		}
		public void Logging(LogHandler handler)
		{
			db.OnLog += handler;
		}
		public void UnLogging(LogHandler handler)
		{
			db.OnLog -= handler;
		}
		public DbTrans BeginTransaction()
		{
			DbTrans = new DbTrans(db.BeginTransaction());
			return DbTrans;
		}
		public DbTrans BeginTransaction(IsolationLevel il)
		{
			DbTrans = new DbTrans(db.BeginTransaction(il));
			return DbTrans;
		}
		public void RollbackTransaction()
		{
			if (DbTrans != null)
			{
				DbTrans.Rollback();
			}
		}
		public void CommitTransaction()
		{
			if (DbTrans != null)
			{
				DbTrans.Commit();
			}
		}
		public void CloseTransaction()
		{
			if (DbTrans != null)
			{
				DbTrans.Close();
				DbTrans = null;
			}
		}
		public void CloseTransaction(DbTransaction tran)
		{
			db.CloseConnection(tran);
		}
		public string BuildDbParamName(string name)
		{
			Guard.IsNotNullOrEmpty(name, "name");
			return db.DbProvider.BuildParameterName(name);
		}
		public int Update<T>(T entity) where T : Entity
		{
			if (entity.GetChangedFields().Count == 0)
			{
				return 0;
			}
			WhereExpression primaryKeyWhere = DataHelper.GetPrimaryKeyWhere(entity);
			Guard.Check(!WhereExpression.IsNullOrEmpty(primaryKeyWhere), TextResource.MustSetupPK);
			return Update<T>(entity, primaryKeyWhere);
		}
		public void Update<T>(params T[] entities) where T : Entity
		{
			if (entities == null || entities.Length == 0)
			{
				return;
			}
			if (DbTrans == null)
			{
				using (DbTrans dbTrans = BeginTransaction())
				{
					for (int i = 0; i < entities.Length; i++)
					{
						T entity = entities[i];
						Update<T>(entity);
					}
					dbTrans.Commit();
					return;
				}
			}
			for (int j = 0; j < entities.Length; j++)
			{
				T entity2 = entities[j];
				Update<T>(entity2);
			}
		}
		public int Update<T>(T entity, WhereExpression where) where T : Entity
		{
			if (entity.GetChangedFields().Count == 0)
			{
				return 0;
			}
			return ExecuteNonQuery(cmdBulider.CreateUpdateCommand<T>(entity, where));
		}
		public int Update<T>(Field field, object value, WhereExpression where) where T : Entity
		{
			if (Field.IsNullOrEmpty(field))
			{
				return 0;
			}
			return ExecuteNonQuery(cmdBulider.CreateUpdateCommand<T>(new[]
			{
				field
			}, new[]
			{
				value
			}, where));
		}
		public int Update<T>(Dictionary<Field, object> fieldValue, WhereExpression where) where T : Entity
		{
			if (fieldValue == null || fieldValue.Count == 0)
			{
				return 0;
			}
			Field[] array = new Field[fieldValue.Count];
			object[] array2 = new object[fieldValue.Count];
			int num = 0;
			foreach (KeyValuePair<Field, object> current in fieldValue)
			{
				array[num] = current.Key;
				array2[num] = current.Value;
				num++;
			}
			return ExecuteNonQuery(cmdBulider.CreateUpdateCommand<T>(array, array2, where));
		}
		public int Update<T>(Field[] fields, object[] values, WhereExpression where) where T : Entity
		{
			if (fields == null || fields.Length == 0)
			{
				return 0;
			}
			return ExecuteNonQuery(cmdBulider.CreateUpdateCommand<T>(fields, values, where));
		}
		public int Delete<T>(T entity) where T : Entity
		{
			Guard.Check(!EntityHelper.IsReadOnly<T>(), TextResource.CanNotReadOnly.FormatWith(new object[]
			{
				EntityHelper.GetName<T>()
			}));
			WhereExpression primaryKeyWhere = DataHelper.GetPrimaryKeyWhere(entity);
			Guard.Check(!WhereExpression.IsNullOrEmpty(primaryKeyWhere), TextResource.MustSetupPK);
			return Delete<T>(primaryKeyWhere);
		}
		public int Delete<T>(params object[] pkValues) where T : Entity
		{
			return DeleteByPrimaryKey<T>(pkValues);
		}
		public int Delete<T>(params string[] pkValues) where T : Entity
		{
			return DeleteByPrimaryKey<T>(pkValues);
		}
		internal int DeleteByPrimaryKey<T>(params object[] pkValues) where T : Entity
		{
			Guard.Check(!EntityHelper.IsReadOnly<T>(), TextResource.CanNotReadOnly.FormatWith(new object[]
			{
				EntityHelper.GetName<T>()
			}));
			return ExecuteNonQuery(cmdBulider.CreateDeleteCommand(EntityHelper.GetName<T>(), DataHelper.GetPrimaryKeyWhere<T>(pkValues)));
		}
		public int Delete<T>(WhereExpression where) where T : Entity
		{
			Guard.Check(!EntityHelper.IsReadOnly<T>(), TextResource.CanNotReadOnly.FormatWith(new object[]
			{
				EntityHelper.GetName<T>()
			}));
			return ExecuteNonQuery(cmdBulider.CreateDeleteCommand(EntityHelper.GetName<T>(), where));
		}
		public void Insert<T>(params T[] entities) where T : Entity
		{
			if (entities == null || entities.Length == 0)
			{
				return;
			}
			for (int i = 0; i < entities.Length; i++)
			{
				T entity = entities[i];
				Insert<T>(entity);
			}
		}
		public int Insert<T>(T entity) where T : Entity
		{
			return insertExecute<T>(cmdBulider.CreateInsertCommand<T>(entity));
		}
		public int Insert<T>(Field[] fields, object[] values) where T : Entity
		{
			return insertExecute<T>(cmdBulider.CreateInsertCommand<T>(fields, values));
		}
		private int insertExecute<T>(DbCommand cmd) where T : Entity
		{
			if (cmd == null)
			{
				return 0;
			}
			Field identityField = EntityHelper.GetIdentityField<T>();
			if (Field.IsNullOrEmpty(identityField))
			{
				return ExecuteNonQuery(cmd);
			}
			object obj;
			if (Db.DbProvider is MsAccessProvider)
			{
				ExecuteNonQuery(cmd);
				obj = ExecuteScalar(db.GetSqlStringCommand(string.Format("select max({0}) from {1}", identityField.FieldName, identityField.TableName)));
			}
			else
			{
				if (Db.DbProvider.SupportBatch)
				{
					cmd.CommandText = cmd.CommandText + ";" + db.DbProvider.RowAutoID;
					obj = ExecuteScalar(cmd);
				}
				else
				{
					ExecuteNonQuery(cmd);
					obj = ExecuteScalar(db.GetSqlStringCommand(Db.DbProvider.RowAutoID));
				}
			}
			if (obj == null || Convert.IsDBNull(obj))
			{
				return 0;
			}
			return Convert.ToInt32(obj);
		}
		public int ExecuteNonQuery(DbCommand cmd)
		{
			if (cmd == null)
			{
				return 0;
			}
			if (DbTrans != null)
			{
				return db.ExecuteNonQuery(cmd, DbTrans);
			}
			return db.ExecuteNonQuery(cmd);
		}
		public object ExecuteScalar(DbCommand cmd)
		{
			if (cmd == null)
			{
				return null;
			}
			if (DbTrans != null)
			{
				return db.ExecuteScalar(cmd, DbTrans);
			}
			return db.ExecuteScalar(cmd);
		}
		public IDataReader ExecuteReader(DbCommand cmd)
		{
			if (cmd == null)
			{
				return null;
			}
			if (DbTrans != null)
			{
				return db.ExecuteReader(cmd, DbTrans);
			}
			return db.ExecuteReader(cmd);
		}
		public DataSet ExecuteDataSet(DbCommand cmd)
		{
			if (cmd == null)
			{
				return null;
			}
			if (DbTrans != null)
			{
				return db.ExecuteDataSet(cmd, DbTrans);
			}
			return db.ExecuteDataSet(cmd);
		}
		public int ExecuteNonQuery(string commandText)
		{
			DbCommand cmd = db.CreateCommandByCommandType(CommandType.Text, commandText);
			return ExecuteNonQuery(cmd);
		}
		public object ExecuteScalar(string commandText)
		{
			DbCommand cmd = db.CreateCommandByCommandType(CommandType.Text, commandText);
			return ExecuteScalar(cmd);
		}
		public IDataReader ExecuteReader(string commandText)
		{
			DbCommand cmd = db.CreateCommandByCommandType(CommandType.Text, commandText);
			return ExecuteReader(cmd);
		}
		public DataSet ExecuteDataSet(string commandText)
		{
			DbCommand cmd = db.CreateCommandByCommandType(CommandType.Text, commandText);
			return ExecuteDataSet(cmd);
		}
	}
}
